package com.yixuan.mt.core.handler;

import com.yixuan.mt.common.constant.PathConstant;
import com.yixuan.mt.core.constant.ServerConstant;
import com.yixuan.mt.core.response.FixedResponse;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

@Component
public class GetFileController extends AbstractController {
    @Override
    void handle(ChannelHandlerContext ctx, HttpRequest httpRequest, HttpContent httpContent) throws IOException {
        File file = new File(PathConstant.FILE_RESOURCE_PATH_PREFIX_MYSQL + httpRequest.uri() +  httpRequest.uri().substring(httpRequest.uri().lastIndexOf("/")));
        if (!file.exists() || !file.isFile()) {
            FixedResponse.sendNotFoundResponse(ctx);
            return;
        }

        HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
        response.headers().set(HttpHeaderNames.CONTENT_TYPE, "image/png");
        response.headers().set(HttpHeaderNames.CONTENT_LENGTH, file.length());
        response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
        ctx.writeAndFlush(response);

        // 边读取边写回给客户端, 避免把整个文件都读入内存
        ByteBuf buffer = Unpooled.buffer(ServerConstant.RESPONSE_BUFFER_SIZE);
        ByteBuffer byteBuffer = buffer.nioBuffer(0, ServerConstant.RESPONSE_BUFFER_SIZE);
        RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
        FileChannel channel = randomAccessFile.getChannel();
        try (randomAccessFile; channel) {
            int readBytes;
            while ((readBytes = channel.read(byteBuffer)) > 0) {
                buffer.retain();
                buffer.writerIndex(readBytes);
                ctx.writeAndFlush(buffer);
                byteBuffer.clear();
            }
        }
    }
}
